# This file is part of ModularBot.
# Copyright (C) 2005 Pierre Ducroquet (pierre.linux59@wanadoo.fr)

# ModularBot is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# ModularBot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with ModularBot; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import base_logic, rightsManager, imp, codeChecker, os.path, sys
from decorators import *

class adminLogic(base_logic.Base):
	"""Contains the logics related calls"""
	def __init__(self, core):
		base_logic.Base.__init__(self, core)
		self.core = core
	
	@admin
	def Call_load (self, context, logic):
		"""Load a logic"""
		if not(logic.startswith("!")):
			if os.path.isfile("logics/%sLogic.py" % logic):
				fh = open("logics/%sLogic.py" % logic)
				sourceCode = ""
				for line in fh.read().splitlines():
					if not(line.startswith("#")) and not(len(line)) < 1:
						sourceCode = sourceCode + line + "\n"
				#sourceCode = fh.read()
				fh.close()
				try:
					codeObj = compile(sourceCode, logic + "Logic.py", "exec")
					codeChecker.safetyCheck(codeObj)
				except codeChecker.SecurityException:
					infos = sys.exc_info()
					sys.excepthook(infos[0], infos[1], infos[2])
					context.say("A security exception occured, logic cannot be loaded.")
					context.say(infos[1].message)
					return
				except SyntaxError:
					# Forget the problem currently
					print sourceCode
					infos = sys.exc_info()
					sys.excepthook(infos[0], infos[1], infos[2])
					context.say("Don't forget to fix this")
					pass
		else:
			logic = logic[1:]
		if not self.core.open_logic(logic):
			if "@" in logic and self.core.has_logic(logic.split("@", 1)[0]):
				context.say("Logic %s already loaded globally", logic)
			else:
				context.say("Unable to load %s" % logic)
		else:
			context.say("Logic loaded")
	
	@admin
	def Call_save (self, context):
		"""Save all the persistent dictionnaries"""
		for logic in self.core.logics.values():
			logic.save()
	
	@admin
	def Call_unload (self, context):
		"""Unload a logic"""
		if self.core.close_logic(context.command_args):
			context.say("Logic %s closed" % context.command_args)
		else:
			context.say("Logic %s is not loaded" % context.command_args)
	
	@admin
	def Call_modules (self, context):
		"""List all opened logic"""
		result = "Logics loaded : "
		for logic_name in self.core.logics.keys():
			result += logic_name + " ; "
		context.say(result[:-2])
	
	@admin
	def Call_join (self, context):
		self.bot.join (context.command_args)
	
	@admin
	def Call_leave (self, context):
		if context.command_args.startswith("#"):
			(chan, reason) = context.command_args.split(" ", 1)
		else:
			chan, reason = context.channel, context.command_args
		self.bot.leave(chan, reason)

	@admin
	def Call_reload_config (self, context):
		self.core.config.parse()
		context.say("Config reloaded")

	@admin
	def Call_reload_rights (self, context):
		if self.core.rights.config == self.core.config.rights:
			# The parse() fonction of the rightsManager is doing the job for us...
			self.core.rights.parse()
		else:
			self.core.rights.close()
			self.core.rights = rightsManager.RightsManager(self.core.config.rights)
		context.say("Rights reloaded")
	
	@admin
	def Call_change_flood_manager (self, context):
		mod = imp.load_source("", "floodmanager.py")
		if hasattr(mod, context.command_args):
			self.bot.setFloodManager(getattr(mod, context.command_args))
			context.say("Flood manager changed...")
		else:
			context.say("Flood manager %s not found..." % context.command_args)
	
	def Call_login (self, context, message):
		self.core.last_arg = ""
		if self.core.rights.login (context.user, message):
			context.say ("You're logged in yet")
		else:
			context.say ("You can't be logged in !")
	
	def leftevent (self, channel, user, chan):
		if self.core.rights.logged_in(user):
			self.core.rights.logout(user)
	
	def kickevent (self, channel, user, chan, kicker, reason):
		if self.core.rights.logged_in(user):
			self.core.rights.logout(user)
		
	def renameevent (self, oldname, newname):
		if self.core.rights.logged_in(oldname):
			self.core.rights.logout(oldname)
	
	def Call_logout (self, context):
		if self.core.rights.logout (context.user):
			context.say ("You're logged out yet")
		else:
			context.say ("You can't be logged out !")
	
	def Call_help (self, context):
		"""If called with an argument (a call name), shows help about this call, else lists
		all available calls"""
		if context.command_args.strip() == "":
			context.say("Available commands :")
			for logic in self.core.logics.keys():
				liste = []
				for fct in dir(self.core.logics[logic]):
					if fct.startswith("Call_"):
						name = fct[5:]
						if hasattr(getattr(self.core.logics[logic], fct), "is_admin"):
							name = "*%s*" % name
						if hasattr(getattr(self.core.logics[logic], fct), "threaded"):
							name = "T:%s" % name
						liste.append(name)
				for alias in self.core.logics[logic].alias:
					liste.append(alias)
				if len(liste) > 0:
					context.say("In %s : %s" % (logic, str(liste)))
		else:
			command = context.command_args.strip()
			if not self.core.commands.has_key(command):
				context.say("Command %s not found" % command)
			else:
				coreCommand = self.core.commands[command]
				(logicName, funcName) = coreCommand.get_func(context)
				if logicName == "" or funcName == "":
					context.say("Command %s not found" % command)
				else:
					cmd_func = getattr(self.core.logics[logicName], funcName)
					if cmd_func.__doc__ == "" or cmd_func.__doc__ == None:
						context.say("The command %s is not documented" % command)
					else:
						context.say(cmd_func.__doc__)
	
	def Call_help_logic (self, context):
		"""Gives informations about a logic"""
		msg = context.command_args.strip()
		if msg == "":
			context.say ("A logic name is required as argument")
		else:
			if self.core.logics.has_key(msg):
				logic = self.core.logics[msg]
				if logic.__doc__ == "" or logic.__doc__ == None:
					context.say("The logic %s is not documented" % msg)
				else:
					context.say(logic.__doc__)
			else:
				context.say ("No logic loaded with the name %s" % msg)
